package 直连版本;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;

public class Gobang_B {
    private Frame f = new JFrame("五子棋_直连版本");
    //棋盘 棋子的图片
    BufferedImage table = ImageIO.read(new File("Image\\棋盘.jpg"));
    BufferedImage Black = ImageIO.read(new File("Image\\Black.png"));
    BufferedImage White = ImageIO.read(new File("Image\\White.png"));
    BufferedImage selected = ImageIO.read(new File("Image\\标记.png"));


    //你赢了么
    boolean is_win = false;
    //赢得对话框
    Dialog win = new Dialog(f,"游戏结束",true);
    Button ok = new Button("ok");
    Button again = new Button("again");

    //棋盘的宽高
    final int TABLE_WHITH = 741;
    final int TABLE_HEIGHT = 741;

    //可以容纳的棋子数
    final int BOARD_SIZE = 19;

    //每个棋子占用棋盘的比率
    final int RATE = 37;//TABLE_WHITH / BOARD_SIZE;

    //棋子对于x方向和y方向的偏移量
    final int X_OFFSET = 19;
    final int Y_OFFSET = 19;

    //声明一个二维数组,记录棋子
    //0为棋子 1为白起 2为黑棋
    public int[][] board = new int[BOARD_SIZE][BOARD_SIZE];
    //棋子的颜色
    int board_type = 1;

    //轮到你下了么?
    boolean is_you = board_type==2;
    Label is_you_label = new Label();

    //选择框 二维数组的格数
    int selected_X = -1;
    int selected_Y = -1;

    public Gobang_B() throws IOException {
        new Gobang_B.Send().start();
        new Gobang_B.Receive().start();
    }

    //画布
    private class ChessBoard extends JPanel {
        @Override
        public void paint(Graphics g) {
            //绘图
            g.drawImage(table, 0, 0, TABLE_WHITH,TABLE_HEIGHT,null);
            //绘制选择框
            if (selected_X >= 0 && selected_Y >= 0 && selected_X < BOARD_SIZE && selected_Y < BOARD_SIZE) {
                g.drawImage(selected, selected_X * RATE + X_OFFSET, selected_Y * RATE + Y_OFFSET, null);
            }
            //绘制棋子
            for (int i = 0; i < BOARD_SIZE; i++) {
                for (int j = 0; j < BOARD_SIZE; j++) {
                    //绘制黑棋
                    if (board[i][j] == 2) {
                        g.drawImage(Black, i * RATE + X_OFFSET, j * RATE + Y_OFFSET,37,37, null);
                    }
                    //绘制白棋
                    if (board[i][j] == 1) {
                        g.drawImage(White, i * RATE + X_OFFSET, j * RATE + Y_OFFSET,37,37, null);
                    }
                }
            }

        }
    }

    ChessBoard chessBoard = new Gobang_B.ChessBoard();

//TODO 菜单条还是等到网络通信后再去做


    public void init() throws IOException {
        //处理鼠标移动
        chessBoard.addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                is_you_label.setText(is_you ? "It's your turn":"It's each other's turn");
                selected_X = (e.getX() - X_OFFSET) / RATE;
                selected_Y = (e.getY() - Y_OFFSET) / RATE;

                chessBoard.repaint();
            }
        });

        //处理鼠标点击
        chessBoard.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                int x = e.getX(),y = e.getY();
                int i = (e.getX() - X_OFFSET) / RATE,j=(e.getY() - Y_OFFSET) / RATE;
                if(is_you & Rule.can_Put_it_here(board,i,j)){
                    board[i][j] = board_type;
                    System.out.println(Rule.is_win(board, BOARD_SIZE, i, j));
                    chessBoard.repaint();
                    if(Rule.is_win(board,19,i,j)){
                        send("you fail");
                        is_win = true;
                        win.setVisible(true);
                    }else{
                        send("set " + i + " " + j + " " + board_type);
                    }
                    is_you=false;
                }
                else {
                    //TODO 重复棋子弹出对话
                }
            }

            @Override
            public void mouseExited(MouseEvent e) {
                selected_X = -1;
                selected_Y = -1;
                chessBoard.repaint();
            }
        });

        //结束对话框
        Box box = Box.createVerticalBox();
        box.add(new Label(is_win?"你赢了":"你输了"));
        ok.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                send("886");
                close_all();
                System.exit(0);
            }
        });
        box.add(ok);
        box.add(again);
        win.add(box);
        win.setBounds(500,300,200,150);
        win.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                send("886");
                close_all();
                System.exit(0);
            }
        });
        //直接关闭窗口
        f.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                send("886");
                close_all();
                System.exit(0);
                //TODO 关闭事件仍需联动处理
            }
        });
        //组装棋盘
        chessBoard.setPreferredSize(new Dimension(TABLE_WHITH, TABLE_HEIGHT));
        f.add(chessBoard);
        f.add(is_you_label,BorderLayout.NORTH);
        f.pack();
        f.setVisible(true);
    }

    //命令分析
    //[43.249.193.55:54171]
    Socket s=new Socket("219.150.218.20",24653);
    BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
    BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));//写数据流

    ArrayBlockingQueue<String> Send_queue = new ArrayBlockingQueue<>(50);//发送队列
    Object send_lock=new Object();//发送锁
    //是否退出该方法
    private boolean socket_exit = false;

    //发送数据
    public void send(String msg){
        synchronized (send_lock) {
            Send_queue.add(msg);
            send_lock.notifyAll();
        }
    }


    //关闭所有的流
    public void close_all() {
        socket_exit=false;
        try {
            br.close();
            bw.close();
            s.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //发送线程
    class Send extends Thread{
        @Override
        public void run() {
            synchronized (send_lock){
                while (true){
                    if(!Send_queue.isEmpty()){
                        try {
                            bw.write(Send_queue.remove());
                            bw.newLine();
                            bw.flush();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if(socket_exit)break;
                    try {
                        send_lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }

    //接收线程
    class Receive extends Thread{
        @Override
        public void run() {
            System.out.println("接收线程开始运行...");
            while (!socket_exit){
                String readLine = null;
                try {
                    readLine = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                String[] split = readLine.split(" ");
                System.out.println("接收:" + readLine);
                //TODO 作为命令处理
                if (split[0].equals("set")){
                    int x=Integer.parseInt(split[1]),y=Integer.parseInt(split[2]);
                    System.out.println("对方下棋:" + x + " " + y);
                    board[x][y] = split[3].equals("2")?2:1;
                    is_you = true;
                    chessBoard.repaint();
                }else if(split[0].equals("you")){
                    win.setVisible(true);
                }
                else {
                    System.out.println("有未处理的命令:" + readLine);
                }
            }
        }
    }


    public static void main(String[] args) throws IOException {

        new Gobang_B().init();
    }
}